题目大意
一个冒险家从1号房间出发时,有100点能量值,然后题目中给出从一个房间能到达另一个房间的路,然后到达每个房间能获得的能量值(-100到100),当冒险家的能量值小于或等于0时游戏结束,然后判断是否能达到房间n;
思路
1.这题其实就是求最长路的问题;
2.首先我们用floyd算法来求各房间的连通性;
3.然后用bellman_frod算法来求解到达各房间的能量值;
code
#include <iostream>
#include <fstream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f;
struct Edge
{
int from, to;
};
int w[105];
int dist[105], vis[105], map[105][105];
int n, eNum;
Edge e[5000];
void floyd(){
for(int k = 1; k <= n; ++ k) {
for(int i = 1; i <= n; ++ i) {
if(map[i][k]) {
for(int j = 1; j <= n; ++ j) {
map[i][j] |= (map[i][k] & map[k][j]);
}
}
}
}
}
bool bellman_ford() {
for(int i = 0; i <= n; i ++) {
dist[i] = -INF;
}
dist[1] = 100;
for(int i = 1; i < n; ++ i) {
for(int j = 0; j < eNum; ++ j) {
int from = e[j].from;
int to = e[j].to;
if(dist[to] < dist[from] + w[to] && dist[from] + w[to] > 0) {
dist[to] = dist[from] + w[to];
}
}
}
if(dist[n] > 0) { //当到达n房间的能量值为正时赢得游戏
return true;
}
for(int i = 0; i < eNum; ++ i) {
int from = e[i].from;
int to = e[i].to;
//存在正环且正环上存在房间to能到达房间n
if(dist[from] + w[to] > dist[to] && dist[from] + w[to] > 0 && map[to][n]) {
return true;
}
}
return false;
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);
//ifstream cin("data.in");
while(cin >> n && n != -1) {
eNum = 0;
memset(map, 0, sizeof(map));
for(int i = 1; i <= n; ++ i) {
int num;
cin >> w[i] >> num;
for(int j = 0; j < num; ++ j) {
int to;
cin >> to;
e[eNum].to= to;
e[eNum++].from = i;
map[i][to] = 1;
}
}
floyd();
if(bellman_ford()) {
cout << "winnable" << endl;
}
else{
cout << "hopeless" << endl;
}
}
return 0;
}